package com.zzyl.nursing.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.ServiceCapability;
import com.huaweicloud.sdk.iotda.v5.model.ShowProductRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowProductResponse;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.domain.FamilyMember;
import com.zzyl.nursing.domain.FamilyMemberElder;
import com.zzyl.nursing.dto.*;
import com.zzyl.nursing.mapper.DeviceDataMapper;
import com.zzyl.nursing.mapper.FamilyMemberMapper;
import com.zzyl.nursing.service.*;
import com.zzyl.nursing.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 老人家属Service业务层处理
 *
 * @author mr.wu
 * @date 2025-05-23
 */
@Slf4j
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService {
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private IElderService iElderService;
    @Autowired
    private IFamilyMemberElderService iFamilyMemberElderService;
    @Autowired
    private IDeviceDataService iDeviceDataService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 查询老人家属
     *
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id) {
        return getById(id);
    }

    /**
     * 查询老人家属列表
     *
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember) {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 解绑家人
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteFamilyMember(Integer id) {
        boolean remove = iFamilyMemberElderService
                .remove(Wrappers.<FamilyMemberElder>lambdaQuery()
                        .eq(FamilyMemberElder::getId, id));
        if (!remove) {
            throw new BaseException("解绑失败");
        }
    }

    /**
     * 绑定家人
     *
     * @param familyMemberDTO 老人家属
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertFamilyMember(FamilyMemberDTO familyMemberDTO) {
        //首先先判断老人是否存在  状态（0：禁用，1:启用  2:请假 3:退住中 4入住中 5已退住）
        Elder elder = iElderService.lambdaQuery()
                .eq(Elder::getIdCardNo, familyMemberDTO.getIdCard())
                .eq(Elder::getName, familyMemberDTO.getName()).one();
        //对各种情况进行校验
        if (elder == null) {
            throw new BaseException("该老人不存在");
        } else if (elder.getStatus() == 0) {
            throw new BaseException("该老人账号已禁用，暂时无法绑定，请联系管理员");
        } else if (elder.getStatus() == 5) {
            throw new BaseException("该老人已退住，无法绑定");
        }
        //获取当前的家属信息
        Integer userId = Integer.valueOf(UserThreadLocal.get().get("id").toString());//获取当前登录用户信息
        String userName = UserThreadLocal.get().get("name").toString();//获取当前登录用户信息

        //判断 家人信息是否存在
        FamilyMember familyMember = this.lambdaQuery()
                .eq(FamilyMember::getId, userId)
                .eq(FamilyMember::getName, userName).one();
        if (familyMember == null) {
            throw new BaseException("信息不完善，请先完善信息");
        }
        //存在且状态正常进行维护客户老人关系表(新增)
        FamilyMemberElder familyMemberElder = new FamilyMemberElder();
        familyMemberElder.setElderId(elder.getId());
        familyMemberElder.setFamilyMemberId(familyMember.getId());
        familyMemberElder.setRemark(familyMemberDTO.getRemark());
        boolean save = iFamilyMemberElderService.save(familyMemberElder);
        if (!save) {
            throw new BaseException("绑定失败");
        }
    }

    /**
     * 查询家人列表
     *
     * @return
     */
    @Override
    public List<FamilyVO> myFamilyList() {
        //获取当前的家属信息
        Integer userId = Integer.valueOf(UserThreadLocal.get().get("id").toString());//获取当前登录用户信息
        List<FamilyVO> list = familyMemberMapper.myFamilyList(userId);
        return list;
    }

    /**
     * 查看家人列表（分页查询）
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public List<MyFamilyVO> queryFamily(Integer pageNum, Integer pageSize) {
        Page<MyFamilyVO> page = new Page<>(pageNum, pageSize);
        Integer userId = Integer.valueOf(UserThreadLocal.get().get("id").toString());//获取当前登录用户信息
        List<MyFamilyVO> list = familyMemberMapper.queryFamily(page,userId);
        return list;
    }

    @Autowired
    private IoTDAClient ioTDAClient;

    /**
     * 查询健康数据
     *
     * @param familyMemberDeviceDTO
     * @return
     */
    @Override
    public Map<String, Object> queryDevicePropertyStatus(FamilyMemberDeviceDTO familyMemberDeviceDTO) {
//        //获取设备的iot
        String iotId = iDeviceDataService.lambdaQuery()
                .eq(DeviceData::getDeviceName, familyMemberDeviceDTO.getDeviceName())
                .eq(DeviceData::getProductKey, familyMemberDeviceDTO.getProductKey())
                .select(DeviceData::getIotId)
                .list().get(0)
                .getIotId();
        //到redis中 获取数据
        String data = (String) redisTemplate.opsForHash().get(CacheConstants.IOT_DEVICE_LAST_DATA, iotId);
        List<DeviceData> dataList = JSONUtil.toList(data, DeviceData.class);
        if (CollectionUtils.isEmpty(dataList)) {
            throw new BaseException("数据不存在");
        }
        //从华为云 中获取数据
        ShowProductRequest request = new ShowProductRequest();
        request.withProductId(familyMemberDeviceDTO.getProductKey());
        ShowProductResponse response = ioTDAClient.showProduct(request);
        if (response == null || response.getHttpStatusCode() != 200) {
            throw new BaseException("调用华为云IOT接口查询产品详情失败");
        }
        List<ServiceCapability> serviceCapabilityList = response.getServiceCapabilities();
        if (CollUtil.isEmpty(serviceCapabilityList)) {
            throw new BaseException("没有查询到物模型数据");
        }
        ServiceCapability serviceCapability = serviceCapabilityList.get(0);

        JSONObject jsonObject = JSONUtil.parseObj(serviceCapability);
        String propertiesObj = jsonObject.get("properties").toString();
        // 解析为 JSONArray
        List<PropertyDefinitionDTO> list = JSONUtil.toList(propertiesObj, PropertyDefinitionDTO.class);
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> map1 = new HashMap<>();

        List<MyFamilyDeviceVO> collect = list.stream().map(x -> {
            MyFamilyDeviceVO myFamilyDeviceVO = new MyFamilyDeviceVO();
            myFamilyDeviceVO.setDataType(x.getDataType());
            myFamilyDeviceVO.setIdentifier(x.getPropertyName());
            myFamilyDeviceVO.setName(x.getDescription());
            myFamilyDeviceVO.setUnit(x.getUnit());
            dataList.forEach(d -> {
                if (d.getFunctionId().equals(x.getPropertyName())) {
                    myFamilyDeviceVO.setValue(d.getDataValue());
                    LocalDateTime alarmTime = d.getAlarmTime();
                    long timestampMillis = alarmTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli();
                    myFamilyDeviceVO.setTime(String.valueOf(timestampMillis));
//                    myFamilyDeviceVO.setTime(String.valueOf(d.getAlarmTime()));
                }
            });
            return myFamilyDeviceVO;
        }).collect(Collectors.toList());
        log.info("数据：{}", collect);
// TODO 有一个bug，前端绑定的不是心率的数据，绑定的是用电量，没找打解决办法，手动调换一下数据
        MyFamilyDeviceVO heartRate = null;
        MyFamilyDeviceVO battery = null;

        for (MyFamilyDeviceVO device : collect) {
            if ("HeartRate".equals(device.getIdentifier())) {
                heartRate = device;
            } else if ("BatteryPercentage".equals(device.getIdentifier())) {
                battery = device;
            }
        }

        if (heartRate != null && battery != null) {
            String temp = heartRate.getValue();
            heartRate.setValue(battery.getValue());
            battery.setValue(temp);
        }

        map1.put("propertyStatusInfo", collect);
        map.put("list", map1);
        log.info("数据：{}", map);
        return map;
    }

    @Autowired
    private DeviceDataMapper deviceDataMapper;

    /**
     * 按天统计查询指标数据
     *
     * @param dayDeviceDTO
     * @return
     */
    @Override
    public List<DayDeviceValueVO> queryDeviceDataListByDay(DayDeviceDTO dayDeviceDTO) {
        log.info("按天统计查询指标数据：{}", dayDeviceDTO);
        LocalDateTime startTime = LocalDateTimeUtil.of(dayDeviceDTO.getStartTime());
        LocalDateTime endTime = LocalDateTimeUtil.of(dayDeviceDTO.getEndTime());
        dayDeviceDTO.setBegin(startTime);
        dayDeviceDTO.setEnd(endTime);
        List<DayDeviceValueVO> list = deviceDataMapper.queryDeviceDataListByDay(dayDeviceDTO);
        return list;
    }

    /**
     * 按周统计查询指标数据
     *
     * @return
     */
    @Override
    public List<DayDeviceValueVO> queryDeviceDataListByWeek(DayDeviceDTO dayDeviceDTO) {
        List<DayDeviceValueVO> list = deviceDataMapper.queryDeviceDataListByWeek(dayDeviceDTO);
        return list;
    }

    /**
     * 修改老人家属
     *
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember) {
        return updateById(familyMember) ? 1 : 0;
    }

    /**
     * 批量删除老人家属
     *
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除老人家属信息
     *
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    @Autowired
    private WechatService wechatService;

    /**
     * 用户昵称名前缀集合
     */
    private static List<String> NICK_NAME_PREFIX_LIST = Arrays.asList("钱途无量",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝");

    @Autowired
    private TokenService tokenService;

    /**
     * 小程序登录
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoginUserVo login(LoginUserDto dto) {
        //1. 调用微信小程序登录接口获取openId
        String openId = wechatService.getOpenId(dto.getCode());
        if (StringUtils.isBlank(openId)) {
            throw new BaseException("获取openId失败");
        }

        //2. 根据openId查询用户数据
        FamilyMember member = this.lambdaQuery().eq(FamilyMember::getOpenId, openId).one();

        //3. 如果用户不存在，则新增用户（自动注册）
        if (member == null) {
            Collections.shuffle(NICK_NAME_PREFIX_LIST);

            //随机生成昵称
            String nickName = NICK_NAME_PREFIX_LIST.get(0) + RandomStringUtils.randomNumeric(4);

            member = FamilyMember.builder().name(nickName).openId(openId).build();
            boolean result = this.save(member);
            if (!result) {
                throw new BaseException("新增用户失败");
            }
        }

        //4. 判断用户手机号如果不存在，则调用微信获取手机号接口得到手机号
        if (StringUtils.isBlank(member.getPhone())) {
            String phone = wechatService.getPhone(dto.getPhoneCode());
            if (StringUtils.isBlank(phone)) {
                throw new BaseException("获取手机号失败");
            }

            //5. 得到手机号后则完成用户表的更新
            boolean result = this.lambdaUpdate().eq(FamilyMember::getId, member.getId())
                    .set(FamilyMember::getPhone, phone).update();
            if (!result) {
                throw new BaseException("更新手机号失败");
            }
        }

        //6. 生成登录成功用户的令牌（Token）
        Map<String, Object> userMap = new HashMap<>();
        userMap.put("userId", member.getId());//设置用户
        userMap.put("name", member.getName());//用户昵称
        String token = tokenService.createToken(userMap);//生成令牌

        //7. 构建响应数据
        return LoginUserVo.builder().nickName(member.getName()).token(token).build();
    }


}


/*
        List<DeviceData> list = iDeviceDataService.lambdaQuery()
                .eq(DeviceData::getDeviceName, familyMemberDeviceDTO.getDeviceName())
                .eq(DeviceData::getProductKey, familyMemberDeviceDTO.getProductKey())
                .list();
        ShowProductRequest request = new ShowProductRequest();
        request.withProductId(familyMemberDeviceDTO.getProductKey());
        ShowProductResponse response = ioTDAClient.showProduct(request);
         if(response==null || response.getHttpStatusCode()!=200) {
            throw new BaseException("调用华为云IOT接口查询产品详情失败");
        }
         List<ServiceCapability> serviceCapabilityList = response.getServiceCapabilities();
        ServiceCapability serviceCapability = serviceCapabilityList.get(0);
         JSONObject jsonObject = JSONUtil.parseObj(serviceCapability);
         if(CollUtil.isEmpty(serviceCapabilityList)){
             throw new BaseException("没有查询到物模型数据");
         }
       JSONUtil.toList( jsonObject.get("properties"),)


        List<MyFamilyDeviceVO> collect = list.stream().map(d -> {
            MyFamilyDeviceVO myFamilyDeviceVO = new MyFamilyDeviceVO();
//            myFamilyDeviceVO.setDataType();
            myFamilyDeviceVO.setIdentifier(d.getFunctionId());
//            myFamilyDeviceVO.setDataType();
//            myFamilyDeviceVO.setDataType();
//            myFamilyDeviceVO.setDataType();
//            myFamilyDeviceVO.setDataType();
            return myFamilyDeviceVO;
        }).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
//        map.put("propertyStatusInfo", collect);
        Map<String, Object> map1 = new HashMap<>();
        map1.put("list", map);
        return map1;
*/